#include "Common.cuh"
#include<vector>
#include<filesystem>
#include <iostream>

namespace fs = std::filesystem;

#pragma region  通用功能函数实现

__device__ __host__ bool gridTiffCode2GridCode(DGGSGridTileCode gridTiffCode, DGGSElementCode& elementCode, int originLevel)
{
    long long row = 0;
    long long col = 0;
    int level = gridTiffCode.level;
    long long morton = gridTiffCode.morton;

    for (int i = 0; i < level - originLevel; ++i) {
        row |= (morton & (1LL << (2 * i + 1))) >> (i + 1);
        col |= (morton & (1LL << (2 * i))) >> i;
    }

    row = row * (long long)pow(2, originLevel);
    col = col * (long long)pow(2, originLevel);

    elementCode.level = level;
    elementCode.basePartition = gridTiffCode.basePartition;
    elementCode.row = row;
    elementCode.col = col;
    return true;
}

/// <summary>
/// 格网编码转GridTIFF编码
/// </summary>
__device__ __host__ bool gridCode2GridTiffCode(DGGSElementCode elementCode, DGGSGridTileCode& gridTiffCode, int originLevel)
{
    long long row = elementCode.row;
    long long col = elementCode.col;
    int level = elementCode.level;

    long long morton = 0;
    row = row / (long long) pow(2,originLevel);
    col = col / (long long) pow(2,originLevel);
    for (int i = 0; i < level - originLevel; ++i) {
        morton |= (col & (1LL << i)) << i | (row & (1LL << i)) << (i + 1);
    }

    gridTiffCode.basePartition = elementCode.basePartition;
    gridTiffCode.morton = morton;
    gridTiffCode.level = level;

    return true;
}

/// <summary>
/// 获取边界
/// </summary>
bool getBoundFromGeoTrans(const double*geoTransform,int xSize,int ySize,double* bound)
{
    if(geoTransform== nullptr)
        return false;
    bound[2]=geoTransform[0];
    bound[3]=geoTransform[0]+xSize*geoTransform[1];
    bound[0]=geoTransform[3];
    bound[1]=geoTransform[3]+ySize*geoTransform[5];
    return true;
}

/// <summary>
/// 获取文件夹下所有文件
/// </summary>
void getAllFilesFromPath(const std::string& folderPath,const char* exFormat, std::string*& files, int& fileCount)
{
    // 用于保存所有文件名
    std::vector<std::string> matchedFiles;

    try {
        // 遍历文件夹内容
        for (const auto& entry : fs::directory_iterator(folderPath)) {
            if (fs::is_regular_file(entry.status())) { // 只获取文件，不获取目录
                std::string filePath = entry.path().string();

                // 获取文件扩展名并转化为小写
                std::string extension = entry.path().extension().string();
                if (extension == exFormat) {
                    matchedFiles.push_back(filePath); // 存储文件路径
                }
            }
        }

        // 将匹配的文件数量赋值给 tileFileCount
        fileCount =(int) matchedFiles.size();

        // 动态分配数组以保存文件路径
        files = new std::string[fileCount];

        // 将文件路径从 matchedFiles 复制到 tileFiles
        for (int i = 0; i < fileCount; ++i) {
            files[i] = matchedFiles[i];
        }
    }
    catch (const std::exception& e) {
        std::cerr << "Error accessing directory: " << e.what() << std::endl;
        fileCount = 0;  // 出现异常时，文件数量设为 0
        files = nullptr;  // 不分配内存
    }
}

/// <summary>
/// 获取文件夹下所有文件夹
/// </summary>
void getAllDirectoriesFromPath(const std::string& folderPath,std::string*& fileDirectories, int& fileDirectoriesCount) {
    std::vector<std::string> directories;

    try {
        for (const auto& entry : fs::directory_iterator(folderPath)) {
            if (entry.is_directory()) {
                std::string  currentDir=folderPath+"/"+entry.path().filename().string();
                directories.push_back(currentDir);
            }
        }
        // 将匹配的文件数量赋值给 tileFileCount
        fileDirectoriesCount =(int) directories.size();

        // 动态分配数组以保存文件路径
        fileDirectories = new std::string[fileDirectoriesCount];

        // 将文件路径从 matchedFiles 复制到 tileFiles
        for (int i = 0; i < fileDirectoriesCount; ++i) {
            fileDirectories[i] = directories[i];
        }

    } catch (const fs::filesystem_error& e) {
        std::cerr << "Error accessing folder: " << e.what() << std::endl;
    }
}


/// <summary>
/// 将格网编码转化为GridTIFF的行列号
/// </summary>
/// <param name="code"></param>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="gridBox"></param>
/// <returns></returns>
__device__ bool code2XY(int row, int col, int rowMin, int colMin, int tileSize, int& x, int& y)
{
    int x0 = 0;
    int y0 = tileSize - 1;

    x = int(row - rowMin + col - colMin + x0);
    y = int((col - colMin) - (row - rowMin) + y0);
    if (y < 0 || x < 0)
    {
        //表示没找到，可以跳过
        x = -1, y = -1;
        return false;
    }
    return true;
}


#pragma endregion